#include "StdAfx.h"
#include "WinDebugMonitor.h"

#define TIMEOUT_WIN_DEBUG	10

CWinDebugMonitor::CWinDebugMonitor()
{
}

CWinDebugMonitor::~CWinDebugMonitor()
{
}

DWORD CWinDebugMonitor::Initialize()
{
	DWORD errorCode = 0;
	BOOL bSuccessful = FALSE;

	SetLastError(0);

	// Mutex: DBWin
	// ---------------------------------------------------------
	CComBSTR DBWinMutex = L"DBWinMutex";
	m_hDBWinMutex = ::OpenMutex(
		MUTEX_ALL_ACCESS, 
		FALSE, 
		DBWinMutex
		);

	if (m_hDBWinMutex == NULL) {
		errorCode = GetLastError();
		return errorCode;
	}

	// Event: buffer ready
	// ---------------------------------------------------------
	CComBSTR DBWIN_BUFFER_READY = L"DBWIN_BUFFER_READY";
	m_hEventBufferReady = ::OpenEvent(
		EVENT_ALL_ACCESS,
		FALSE,
		DBWIN_BUFFER_READY
		);

	if (m_hEventBufferReady == NULL) {
		m_hEventBufferReady = ::CreateEvent(
			NULL,
			FALSE,	// auto-reset
			TRUE,	// initial state: signaled
			DBWIN_BUFFER_READY
			);

		if (m_hEventBufferReady == NULL) {
			errorCode = GetLastError();
			return errorCode;
		}
	}

	// Event: data ready
	// ---------------------------------------------------------
	CComBSTR DBWIN_DATA_READY = L"DBWIN_DATA_READY";
	m_hEventDataReady = ::OpenEvent(
		SYNCHRONIZE,
		FALSE,
		DBWIN_DATA_READY
		);

	if (m_hEventDataReady == NULL) {
		m_hEventDataReady = ::CreateEvent(
			NULL,
			FALSE,	// auto-reset
			FALSE,	// initial state: nonsignaled
			DBWIN_DATA_READY
			);

		if (m_hEventDataReady == NULL) {
			errorCode = GetLastError();
			return errorCode;
		}
	}

	// Shared memory
	// ---------------------------------------------------------
	CComBSTR DBWIN_BUFFER = L"DBWIN_BUFFER";
	m_hDBMonBuffer = ::OpenFileMapping(
		FILE_MAP_READ,
		FALSE,
		DBWIN_BUFFER
		);

	if (m_hDBMonBuffer == NULL) {
		m_hDBMonBuffer = ::CreateFileMapping(
			INVALID_HANDLE_VALUE,
			NULL,
			PAGE_READWRITE,
			0,
			sizeof(struct DbgBuffer),
			DBWIN_BUFFER
			);

		if (m_hDBMonBuffer == NULL) {
			errorCode = GetLastError();
			return errorCode;
		}
	}

	m_pDBBuffer = (struct DbgBuffer *)::MapViewOfFile(
		m_hDBMonBuffer,
		SECTION_MAP_READ,
		0,
		0,
		0
		);

	if (m_pDBBuffer == NULL) {
		errorCode = GetLastError();
		return errorCode;
	}

	return errorCode;
}

void CWinDebugMonitor::Unintialize()
{
	if (m_hWinDebugMonitorThread != NULL) {
		m_bWinDebugMonStopped = TRUE;
		::WaitForSingleObject(m_hWinDebugMonitorThread, INFINITE);
	}

	if (m_hDBWinMutex != NULL) {
		CloseHandle(m_hDBWinMutex);
		m_hDBWinMutex = NULL;
	}

	if (m_hDBMonBuffer != NULL) {
		::UnmapViewOfFile(m_pDBBuffer);
		CloseHandle(m_hDBMonBuffer);
		m_hDBMonBuffer = NULL;
	}

	if (m_hEventBufferReady != NULL) {
		CloseHandle(m_hEventBufferReady);
		m_hEventBufferReady = NULL;
	}

	if (m_hEventDataReady != NULL) {
		CloseHandle(m_hEventDataReady);
		m_hEventDataReady = NULL;
	}

	m_pDBBuffer = NULL;
}

DWORD CWinDebugMonitor::GetOutputString()
{
	DWORD ret = 0;

	// wait for data ready
	ret = ::WaitForSingleObject(m_hEventDataReady, TIMEOUT_WIN_DEBUG);

	if (ret == WAIT_OBJECT_0)
	{
		memcpy_s(&m_stBuffer, sizeof(DbgBuffer), m_pDBBuffer, sizeof(DbgBuffer));

		// signal buffer ready
		SetEvent(m_hEventBufferReady);
	}

	return ret;
}